/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package logicanegocio;

import entities.Categoria;
import entities.CategoriaPK;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entities.Estadio;
import entities.Precio;
import java.util.ArrayList;
import java.util.List;
import entities.Silla;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import logicanegocio.exceptions.IllegalOrphanException;
import logicanegocio.exceptions.NonexistentEntityException;
import logicanegocio.exceptions.PreexistingEntityException;

/**
 *
 * @author Alejandro
 */
public class CategoriaJpaController implements Serializable {

    public CategoriaJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Categoria categoria) throws PreexistingEntityException, Exception {
        if (categoria.getCategoriaPK() == null) {
            categoria.setCategoriaPK(new CategoriaPK());
        }
        if (categoria.getPrecioList() == null) {
            categoria.setPrecioList(new ArrayList<Precio>());
        }
        if (categoria.getSillaList() == null) {
            categoria.setSillaList(new ArrayList<Silla>());
        }
        categoria.getCategoriaPK().setEstadioIdEstadio(categoria.getEstadio().getIdEstadio().toBigInteger());
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Estadio estadio = categoria.getEstadio();
            if (estadio != null) {
                estadio = em.getReference(estadio.getClass(), estadio.getIdEstadio());
                categoria.setEstadio(estadio);
            }
            List<Precio> attachedPrecioList = new ArrayList<Precio>();
            for (Precio precioListPrecioToAttach : categoria.getPrecioList()) {
                precioListPrecioToAttach = em.getReference(precioListPrecioToAttach.getClass(), precioListPrecioToAttach.getIdPrecio());
                attachedPrecioList.add(precioListPrecioToAttach);
            }
            categoria.setPrecioList(attachedPrecioList);
            List<Silla> attachedSillaList = new ArrayList<Silla>();
            for (Silla sillaListSillaToAttach : categoria.getSillaList()) {
                sillaListSillaToAttach = em.getReference(sillaListSillaToAttach.getClass(), sillaListSillaToAttach.getSillaPK());
                attachedSillaList.add(sillaListSillaToAttach);
            }
            categoria.setSillaList(attachedSillaList);
            em.persist(categoria);
            if (estadio != null) {
                estadio.getCategoriaList().add(categoria);
                estadio = em.merge(estadio);
            }
            for (Precio precioListPrecio : categoria.getPrecioList()) {
                Categoria oldCategoriaOfPrecioListPrecio = precioListPrecio.getCategoria();
                precioListPrecio.setCategoria(categoria);
                precioListPrecio = em.merge(precioListPrecio);
                if (oldCategoriaOfPrecioListPrecio != null) {
                    oldCategoriaOfPrecioListPrecio.getPrecioList().remove(precioListPrecio);
                    oldCategoriaOfPrecioListPrecio = em.merge(oldCategoriaOfPrecioListPrecio);
                }
            }
            for (Silla sillaListSilla : categoria.getSillaList()) {
                Categoria oldCategoriaOfSillaListSilla = sillaListSilla.getCategoria();
                sillaListSilla.setCategoria(categoria);
                sillaListSilla = em.merge(sillaListSilla);
                if (oldCategoriaOfSillaListSilla != null) {
                    oldCategoriaOfSillaListSilla.getSillaList().remove(sillaListSilla);
                    oldCategoriaOfSillaListSilla = em.merge(oldCategoriaOfSillaListSilla);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findCategoria(categoria.getCategoriaPK()) != null) {
                throw new PreexistingEntityException("Categoria " + categoria + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Categoria categoria) throws IllegalOrphanException, NonexistentEntityException, Exception {
        categoria.getCategoriaPK().setEstadioIdEstadio(categoria.getEstadio().getIdEstadio().toBigInteger());
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Categoria persistentCategoria = em.find(Categoria.class, categoria.getCategoriaPK());
            Estadio estadioOld = persistentCategoria.getEstadio();
            Estadio estadioNew = categoria.getEstadio();
            List<Precio> precioListOld = persistentCategoria.getPrecioList();
            List<Precio> precioListNew = categoria.getPrecioList();
            List<Silla> sillaListOld = persistentCategoria.getSillaList();
            List<Silla> sillaListNew = categoria.getSillaList();
            List<String> illegalOrphanMessages = null;
            for (Precio precioListOldPrecio : precioListOld) {
                if (!precioListNew.contains(precioListOldPrecio)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Precio " + precioListOldPrecio + " since its categoria field is not nullable.");
                }
            }
            for (Silla sillaListOldSilla : sillaListOld) {
                if (!sillaListNew.contains(sillaListOldSilla)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Silla " + sillaListOldSilla + " since its categoria field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (estadioNew != null) {
                estadioNew = em.getReference(estadioNew.getClass(), estadioNew.getIdEstadio());
                categoria.setEstadio(estadioNew);
            }
            List<Precio> attachedPrecioListNew = new ArrayList<Precio>();
            for (Precio precioListNewPrecioToAttach : precioListNew) {
                precioListNewPrecioToAttach = em.getReference(precioListNewPrecioToAttach.getClass(), precioListNewPrecioToAttach.getIdPrecio());
                attachedPrecioListNew.add(precioListNewPrecioToAttach);
            }
            precioListNew = attachedPrecioListNew;
            categoria.setPrecioList(precioListNew);
            List<Silla> attachedSillaListNew = new ArrayList<Silla>();
            for (Silla sillaListNewSillaToAttach : sillaListNew) {
                sillaListNewSillaToAttach = em.getReference(sillaListNewSillaToAttach.getClass(), sillaListNewSillaToAttach.getSillaPK());
                attachedSillaListNew.add(sillaListNewSillaToAttach);
            }
            sillaListNew = attachedSillaListNew;
            categoria.setSillaList(sillaListNew);
            categoria = em.merge(categoria);
            if (estadioOld != null && !estadioOld.equals(estadioNew)) {
                estadioOld.getCategoriaList().remove(categoria);
                estadioOld = em.merge(estadioOld);
            }
            if (estadioNew != null && !estadioNew.equals(estadioOld)) {
                estadioNew.getCategoriaList().add(categoria);
                estadioNew = em.merge(estadioNew);
            }
            for (Precio precioListNewPrecio : precioListNew) {
                if (!precioListOld.contains(precioListNewPrecio)) {
                    Categoria oldCategoriaOfPrecioListNewPrecio = precioListNewPrecio.getCategoria();
                    precioListNewPrecio.setCategoria(categoria);
                    precioListNewPrecio = em.merge(precioListNewPrecio);
                    if (oldCategoriaOfPrecioListNewPrecio != null && !oldCategoriaOfPrecioListNewPrecio.equals(categoria)) {
                        oldCategoriaOfPrecioListNewPrecio.getPrecioList().remove(precioListNewPrecio);
                        oldCategoriaOfPrecioListNewPrecio = em.merge(oldCategoriaOfPrecioListNewPrecio);
                    }
                }
            }
            for (Silla sillaListNewSilla : sillaListNew) {
                if (!sillaListOld.contains(sillaListNewSilla)) {
                    Categoria oldCategoriaOfSillaListNewSilla = sillaListNewSilla.getCategoria();
                    sillaListNewSilla.setCategoria(categoria);
                    sillaListNewSilla = em.merge(sillaListNewSilla);
                    if (oldCategoriaOfSillaListNewSilla != null && !oldCategoriaOfSillaListNewSilla.equals(categoria)) {
                        oldCategoriaOfSillaListNewSilla.getSillaList().remove(sillaListNewSilla);
                        oldCategoriaOfSillaListNewSilla = em.merge(oldCategoriaOfSillaListNewSilla);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                CategoriaPK id = categoria.getCategoriaPK();
                if (findCategoria(id) == null) {
                    throw new NonexistentEntityException("The categoria with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(CategoriaPK id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Categoria categoria;
            try {
                categoria = em.getReference(Categoria.class, id);
                categoria.getCategoriaPK();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The categoria with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Precio> precioListOrphanCheck = categoria.getPrecioList();
            for (Precio precioListOrphanCheckPrecio : precioListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Categoria (" + categoria + ") cannot be destroyed since the Precio " + precioListOrphanCheckPrecio + " in its precioList field has a non-nullable categoria field.");
            }
            List<Silla> sillaListOrphanCheck = categoria.getSillaList();
            for (Silla sillaListOrphanCheckSilla : sillaListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Categoria (" + categoria + ") cannot be destroyed since the Silla " + sillaListOrphanCheckSilla + " in its sillaList field has a non-nullable categoria field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Estadio estadio = categoria.getEstadio();
            if (estadio != null) {
                estadio.getCategoriaList().remove(categoria);
                estadio = em.merge(estadio);
            }
            em.remove(categoria);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Categoria> findCategoriaEntities() {
        return findCategoriaEntities(true, -1, -1);
    }

    public List<Categoria> findCategoriaEntities(int maxResults, int firstResult) {
        return findCategoriaEntities(false, maxResults, firstResult);
    }

    private List<Categoria> findCategoriaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Categoria.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Categoria findCategoria(CategoriaPK id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Categoria.class, id);
        } finally {
            em.close();
        }
    }

    public int getCategoriaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Categoria> rt = cq.from(Categoria.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

    public Precio getPrecioCatXPartido(BigInteger idEstadio, BigInteger idCategoria, BigDecimal idPartido) {
        EntityManager em = getEntityManager();
        try {
            Query query = em.createNativeQuery("SELECT * FROM PRECIO P "+
                        "WHERE P.CATEGORIA_ESTADIO_ID_ESTADIO = ? AND "+
                        "P.CATEGORIA_ID_CATEGORIA = ? AND  P.PARTIDO_ID_PARTIDO = ?",Precio.class);
            query.setParameter(1, idEstadio.toString());
            query.setParameter(2, idCategoria.toString());
            query.setParameter(3, idPartido.toString());
            return (Precio) query.getSingleResult();
        } finally {
            em.close();
        }
    }

    public BigDecimal getEntradasDispCategoriaXPartido(BigInteger idEstadio, BigInteger idCategoria, BigDecimal idPartido) {
        EntityManager em = getEntityManager();
        try {
            Query query = em.createNativeQuery(
            "WITH NUMSILLASEST AS (SELECT count(*) AS NUMS FROM SILLA " +
                                     "WHERE SILLA.CATEGORIA_ESTADIO_ID_ESTADIO = ? AND SILLA.CATEGORIA_ID_CATEGORIA = ?), " +
              "NUMOCUPADAS AS (SELECT count(*) AS NUMO FROM SILLAXPARTIDO S " +
                                    "WHERE S.PARTIDO_ID_PARTIDO = ? AND S.SILLA_CAT_ID_CATEGORIA = ? AND S.SILLA_CAT_EST_ID_EST = ?) " +
            "SELECT (NUMSILLASEST.NUMS-NUMOCUPADAS.NUMO) AS TOTAL FROM NUMSILLASEST, NUMOCUPADAS"
            );
            query.setParameter(1, idEstadio.toString());
            query.setParameter(2, idCategoria.toString());
            query.setParameter(3, idPartido.toString());
            query.setParameter(4, idCategoria.toString());
            query.setParameter(5, idEstadio.toString());
            BigDecimal total = (BigDecimal) query.getSingleResult();
            return total;
        } finally {
            em.close();
        }
    }
    
}
